/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package carreras.gui;

import arduino.entidades.Adelantamiento;
import arduino.entidades.Datos;
import arduino.entidades.Rotura;
import arduino.eventos.ArduinoEvent;
import arduino.eventos.ArduinoEventListener;
import arduino.eventos.RespuestaEvent;
import carreras.ArduinoManager;
import carreras.Configuracion;
import carreras.Utilidades;
import carreras.entidades.Carrera;
import carreras.entidades.CarrilCarrera;
import carreras.entidades.CatCorredorAuto;
import carreras.entidades.Competencia;
import carreras.entidades.CorredorAuto;
import carreras.entidades.ManagerTorneo;
import carreras.entidades.TipoTiempo;
import carreras.entidades.TodasCarrerasFinalizadasException;
import carreras.logger.CarrerasLogger;
import carreras.negocio.NegInscripcion;
import java.awt.Color;
import java.awt.Component;
import java.io.IOException;
import java.sql.SQLException;
import javax.swing.JLabel;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellRenderer;

/**
 *
 * @author fanky
 */
public class frmCarrera extends javax.swing.JFrame {
    private static final String TITLE = "Carreras v"+Configuracion.getCurrentSysVersion();
    private ArduinoManager ardmgr;
    private static final String obLocker = "aLock";
    private Carrera carrera_actual;
    private boolean finalizo_competencia_actual = false;
    public static boolean AUTO_INICIA_CARRERA = true;
    private static final int COLUMNA_CORREDOR_ESTADO = 0;
    private static final int COLUMNA_CORREDOR_CATEGORIA = 2;
    
    /** Creates new form frmMain */
    public frmCarrera() {
        //init att
        ardmgr = new ArduinoManager(createEventListener());
        carrera_actual = null;//porque no se sabe cual es la actual
        initComponents();
        //initial config
        init();
        //frame config
        //setExtendedState(javax.swing.JFrame.MAXIMIZED_BOTH);
        addWindowListener(new java.awt.event.WindowAdapter() {

            @Override
            public void windowClosing(java.awt.event.WindowEvent e) {
                //cierro el arduino
                finaliza_comunicacion();
                System.exit(0);
            }
        });
        setTitle(TITLE);
        setLocationRelativeTo(null);
    }
    private void init(){
        lblEstadoGlobal.setText("Estado Actual: "+ManagerTorneo.getInstance().getCompetencia_actual().toString()+" Competicion Ronda: "+ManagerTorneo.getInstance().getCompetencia_actual().getNumero_ronda());
//        ardmgr = new ArduinoManager(createEventListener());
        refresh_tbl_corredores();
        refresh_tbl_tiempos();
    }
    private ArduinoEventListener createEventListener(){
        return new ArduinoEventListener() {

            @Override
            public void EstadoArduino(ArduinoEvent arduino_event) {               
                
                if(arduino_event.getEstado() == ArduinoEvent.ARDUINO_ONLINE){
                    muestraEstado("Arduino ONLINE - Esperando datos...");
                }else{
                    muestraEstado(arduino_event.getMensaje());
                }
            }

            @Override
            public void Estado_Datos(RespuestaEvent respuesta_event) {
                switch (respuesta_event.getNro_evento()) {
                    case RespuestaEvent.CARRIL:
                        if(respuesta_event.getDatos().getTipo()==Datos.CARRIL){
//                            CarrerasLogger.info(frmCarrera.class, "recibiendo tiempos carril");
                            tiempos_carril(respuesta_event);
                        }else if(respuesta_event.getDatos().getTipo()==Datos.ADELANTAMIENTO){
                            CarrerasLogger.info(frmCarrera.class, "hubo adelantamiento");
                            adelantamiento_carril(respuesta_event);
                        }else if(respuesta_event.getDatos().getTipo()==Datos.ROTURA){
                            CarrerasLogger.info(frmCarrera.class, "hubo roturas que");
                            rotura_auto(respuesta_event);
                        }
                        break;                        
                        //TODO: se rompe todo, es un error tendria que reiniciar todo
                    case RespuestaEvent.ERROR:
                        muestraEstado(respuesta_event.getError().getMensaje());
                        //reinicia arduino :D
                        reinicia_comunicacion();
                        break;
                }
            }
            
        };
    }
    private void tiempos_carril(final RespuestaEvent respuesta_event) {
        SwingUtilities.invokeLater(new Runnable() {

            public void run() {
                try {

                    muestraEstado("Recibiendo datos...");
                    arduino.entidades.Carril carril = (arduino.entidades.Carril) respuesta_event.getDatos();
                    CarrerasLogger.info(frmCarrera.class, "actualizando tiempos de carril: " + carril.getNro_carril());
                    carrera_actual.actualizaTiempos(carril);
                    refresh_tbl_tiempos();
//                try{
//                    new carreras.negocio.Carrera().addCarrilCarrera(cc);
//                }catch(SQLException ex){
//                    CarrerasLogger.warn(frmMainOld.class,"sqlex: "+ex.getMessage());
//                    muestraEstado("Problema en datos, AVISE AL ADMINISTRADOR");
//                }
                } catch (IllegalArgumentException ex) {
                    //ignorada, me llego datos de un carril que nada que ver xF
                } catch(SQLException ex){
                    System.err.println("no se pudieron guardar los datos del carril porque: "+ex.getMessage());
                    javax.swing.JOptionPane.showMessageDialog(frmCarrera.this,"Error en datos guardando tiempos");
                    
                }
            }
        });
    }
    private void adelantamiento_carril(final RespuestaEvent respuesta_event){
        SwingUtilities.invokeLater(new Runnable() {

            public void run() {
                try {

                    Adelantamiento adelantamiento = (Adelantamiento) respuesta_event.getDatos();
                    int nro_carril = adelantamiento.getNro_carril();
                    CarrilCarrera c = carrera_actual.getCarril(nro_carril);
                    c.setEsta_actualizado(true);
                    c.setEstado_carrera(CarrilCarrera.ESTADO_ADELANTADO);
                    refresh_tbl_tiempos();
//                try{
//                    new carreras.negocio.Carrera().addCarrilCarrera(cc);
//                }catch(SQLException ex){
//                    CarrerasLogger.warn(frmMainOld.class,"sqlex: "+ex.getMessage());
//                    muestraEstado("Problema en datos, AVISE AL ADMINISTRADOR");
//                }
                } catch (IllegalArgumentException ex) {
                    //ignorada, me llego datos de un carril que nada que ver xF
                }
            }
        });
                            
    }

    private void rotura_auto(final RespuestaEvent respuesta_event) {
        SwingUtilities.invokeLater(new Runnable() {

            public void run() {
                try {
                    Rotura rotura = (Rotura) respuesta_event.getDatos();
                    int nro_carril = rotura.getNro_carril();
                    CarrilCarrera c = carrera_actual.getCarril(nro_carril);
                    c.setEsta_actualizado(true);
                    c.setEstado_carrera(CarrilCarrera.ESTADO_ROTO);
                    refresh_tbl_tiempos();
//                try{
//                    new carreras.negocio.Carrera().addCarrilCarrera(cc);
//                }catch(SQLException ex){
//                    CarrerasLogger.warn(frmMainOld.class,"sqlex: "+ex.getMessage());
//                    muestraEstado("Problema en datos, AVISE AL ADMINISTRADOR");
//                }
                } catch (IllegalArgumentException ex) {
                    //ignorada, me llego datos de un carril que nada que ver xF
                }
            }
        });
    }
    /**
     * actualizo los tiempos de los corredores
     */
    private void refresh_tbl_tiempos(){
            final DefaultTableModel tmodel = new NotEditableTableModel();
            if(carrera_actual == null || carrera_actual.isEmpty()){
                tmodel.setColumnIdentifiers(new Object[]{"Sin Datos - Agrege un auto"});
                tblTiempos.setModel(tmodel);
            }else{
                tmodel.setColumnIdentifiers(new Object[]{"Carril","Nro","Patente","TipoTiempo","Tiempo"});
                for(CarrilCarrera c: carrera_actual){
                    if(c.getEstado_carrera() == CarrilCarrera.ESTADO_ADELANTADO){
                        tmodel.addRow(new Object[]{"Adelantado","","","",""});
                    }else if(c.getEstado_carrera() == CarrilCarrera.ESTADO_ROTO){
                        tmodel.addRow(new Object[]{"Roto","","","",""});
                    }else{
                        CarrerasLogger.debug(frmCarrera.class, "carril "+c.toString());
                        CarrerasLogger.debug(frmCarrera.class, "carril "+c.getTiempos());
                        int i = 0; //para ver si es el inicial
                        for(TipoTiempo tt: c.getTiempos()){
                            if(i==0){
                                tmodel.addRow(new Object[]{c.getNro_carril(),c.getCorredor_auto().getNumero_asignado(),c.getAuto(),tt.getDescripcion(),tt.getTiempo()});
                            }else{
                                tmodel.addRow(new Object[]{"","","",tt.getDescripcion(),tt.getTiempo()});

                            }
                            i++;
                        }
                    }
                }
                tblTiempos.setModel(tmodel);
                if(carrera_actual.isCarreraOver()){
                    //actualizo el estado actual
                    refresh_tbl_corredores();
                    CarrilCarrera winner = carrera_actual.getGanador();
                    javax.swing.JOptionPane.showMessageDialog(this, "GANADOR! "+winner.getCorredor()+" Manejando "+winner.getAuto() , "GANADOR!", javax.swing.JOptionPane.INFORMATION_MESSAGE);
                    finaliza_comunicacion();
                    //voy a la proxima no mas!
                    proxima_carrera();
                    
                }
            }
        
    }
    
    private void muestraEstado(String mensaje){
        CarrerasLogger.info(frmCarrera.class, mensaje);
        lblEstado.setText("Estado: "+mensaje);
    }
    
    private void finalizar_competicion_actual(){
//        this.dispose();
    }
    /**
     * agrega un nuevo corredor a la lista de corredores que 
     * pueden o no, estar jugando una linda carrera :P
     */
    private void agregar_corredor(){
        diagAAutoCorredor diag = new diagAAutoCorredor(this,ManagerTorneo.getInstance().getCompetencia_actual().getCorredoresAutosActivos());
        diag.setVisible(true);
        diag.dispose();
        if(!diagAAutoCorredor.CANCELADO){
            try{
                CorredorAuto ca = diag.getCorredor_auto();
                CarrerasLogger.info(frmCarrera.class, "autocorredor seleccionado nro: "+ca.getNumero_asignado());
                //lo agrego como inscripto para recuperarlo si llega a pasar algo
                new NegInscripcion().addCorredorAuto(ca, ManagerTorneo.getInstance().getTorneo());
                Competencia comp = ManagerTorneo.getInstance().getCompetencia_actual();
                comp.add(ca);
                //obtengo la carrera actual y actualizo los datos de los corredores
                refresh_tbl_corredores();
                //trato de armar la nueva carrera
                try{
                    if(carrera_actual == null || !carrera_actual.isCarreraOver()){//(carrera_actual!=null &&  !carrera_actual.isCarreraOver())){
                        carrera_actual = comp.getSiguienteCarrera();
                        actualiza_carrera();
                        refresh_tbl_tiempos();
                        if(AUTO_INICIA_CARRERA)
                            inicia_comunicacion();
                    }
                }catch(TodasCarrerasFinalizadasException ex){
                    CarrerasLogger.debug(frmCarrera.class,"CarrerasFinalizadas exception");
                    //javax.swing.JOptionPane.show
                }
            }catch(SQLException ex){
                System.err.println("ex agregando carrera: "+ex.getMessage());
                javax.swing.JOptionPane.showMessageDialog(this,"Error en datos cargando carrera");
            }
        }
    }
    private void proxima_carrera(){
        try {
            
            CarrerasLogger.debug(frmCarrera.class, "fin carrera - hubo ganador - obteniendo proxima carrera");
            carrera_actual = null;
            //pido la sig. carrera
            carrera_actual = ManagerTorneo.getInstance().getCompetencia_actual().getSiguienteCarrera();
            carrera_actual.setEstado_carrera(CarrilCarrera.ESTADO_ESPERANDO_DATOS);
            refresh_tbl_corredores();
            actualiza_carrera();
            refresh_tbl_tiempos();
            if(AUTO_INICIA_CARRERA)
                inicia_comunicacion();
        } catch (TodasCarrerasFinalizadasException ex) {
            
            CarrerasLogger.debug(frmCarrera.class, "CarrerasFinalizadas! :)");
            int opc = javax.swing.JOptionPane.showConfirmDialog(this, "Se han Finalizado con todas las carreras\nDesea Iniciar otra ronda?", "Fin Ronda", javax.swing.JOptionPane.OK_CANCEL_OPTION);
            if (opc == javax.swing.JOptionPane.OK_OPTION) {
                nueva_ronda();
                finalizo_competencia_actual = false;
//                ManagerCompetencia.getInstance().nueva_ronda();
//                lblEstadoGlobal.setText("Estado Actual: " + ManagerCompetencia.getInstance().getCompetencia().toString() + " Competicion Ronda: " + ManagerCompetencia.getInstance().getCompetencia().getNumero_ronda());
                
            }else if(opc == javax.swing.JOptionPane.CANCEL_OPTION
                    || opc == javax.swing.JOptionPane.CLOSED_OPTION) {
                //System.exit(0);
                finalizo_competencia_actual = true;
            }
            btnNuevaRonda.setEnabled(finalizo_competencia_actual);
        }
        
    }
    private void nueva_ronda(){
        try{
            ManagerTorneo.getInstance().nueva_ronda();
            lblEstadoGlobal.setText("Estado Actual: " + ManagerTorneo.getInstance().getCompetencia_actual().toString() + " Competicion Ronda: " + ManagerTorneo.getInstance().getCompetencia_actual().getNumero_ronda());
            proxima_carrera();  
        }catch(SQLException ex){
            System.err.println("sqlex: "+ex.getLocalizedMessage());
            javax.swing.JOptionPane.showMessageDialog(this, "No se pudo generar una nueva ronda por problemas en datos");
        }
    }
    /**
     * actualiza la tabla de corredores con sus estados corresp.
     */
    private void refresh_tbl_corredores(){
        final DefaultTableModel tmodel = new NotEditableTableModel();
        final Competencia competencia_actual = ManagerTorneo.getInstance().getCompetencia_actual();
        final CatCorredorAuto caV = competencia_actual.getCorredoresAutosActivos();
        int linea_corriendo = 0;
        if(caV.isEmpty()){
            tmodel.setColumnIdentifiers(new Object[]{"Sin Datos"});
            tblEstadoCorredores.setModel(tmodel);
        }else{
            tmodel.setColumnIdentifiers(new Object[]{"Estado","Numero","Categoria"});
            for(int idx=0;idx<caV.size();idx++){
                CorredorAuto ca = caV.get(idx);
                if(ca.getEstado_carrera()==CarrilCarrera.ESTADO_ESPERANDO_DATOS){
                    linea_corriendo = idx; //va a pisar la ultima asi que siempre muestra la de 'mas abajo'
                }
                tmodel.addRow(new Object[]{ca.getEstadoActual(),ca.getNumero_asignado(),ca.getCategoria().getDescripcion()});
            }
            tblEstadoCorredores.setModel(tmodel);
            tblEstadoCorredores.getColumnModel().getColumn(COLUMNA_CORREDOR_ESTADO).setCellRenderer(new CorredoresAutosEstadoRenderer());
            tblEstadoCorredores.getColumnModel().getColumn(COLUMNA_CORREDOR_CATEGORIA).setCellRenderer(new CorredoresAutosCategoriaRenderer());
            Utilidades.scrollToVisible(tblEstadoCorredores, linea_corriendo, 0);
        }
        
    }
    /**
     * actualizo los datos de los corredores en los carriles corresp.
     */
    private void actualiza_carrera(){
        limpia_paneles_carriles();
        for(CarrilCarrera cc: carrera_actual){
            if(cc.getNro_carril()==1){
                lblC1Apellido.setText(cc.getCorredor_auto().getCorredor().getApellido());
                lblC1Auto.setText(cc.getCorredor_auto().getAuto().getPatente());
                lblC1Cat.setText(cc.getCorredor_auto().getCategoria().getDescripcion());
                lblC1Nombre.setText(cc.getCorredor_auto().getCorredor().getNombre());
                lblC1Numero.setText(String.valueOf(cc.getCorredor_auto().getNumero_asignado()));
            }else if(cc.getNro_carril() == 2){
                lblC2Apellido.setText(cc.getCorredor_auto().getCorredor().getApellido());
                lblC2Auto.setText(cc.getCorredor_auto().getAuto().getPatente());
                lblC2Cat.setText(cc.getCorredor_auto().getCategoria().getDescripcion());
                lblC2Nombre.setText(cc.getCorredor_auto().getCorredor().getNombre());
                lblC2Numero.setText(String.valueOf(cc.getCorredor_auto().getNumero_asignado()));
            }
        }
        
    }
    private void limpia_paneles_carriles(){
        
        lblC1Apellido.setText("");
        lblC1Auto.setText("");
        lblC1Cat.setText("");
        lblC1Nombre.setText("");
        lblC1Numero.setText("");

        lblC2Apellido.setText("");
        lblC2Auto.setText("");
        lblC2Cat.setText("");
        lblC2Nombre.setText("");
        lblC2Numero.setText("");
        
    }
    /**
     * es para ver si hace la prox carrera :D
     * para pasar a la prox, se los pone a todos como ganadores
     */
    private void fuerza_fin(){
        for(CarrilCarrera cc : carrera_actual){
            cc.setEsta_actualizado(true);
            cc.setEstado_carrera(CarrilCarrera.ESTADO_GANADOR);
        }
        proxima_carrera();
    }
    /**
     * cuando concluye la inscripcion ya no se puede hacer mas nada
     * se le generan las categorias a los inscriptos, y se pueden modificar mediante gui
     * luego de eso, mantinen la categoria hasta finalizado el encuentro
     */
    private void fin_inscripcion(){
        try{
            btnAgregarCorredor.setEnabled(false);
            btnFinInscripcion.setEnabled(false);
            btnNuevaRonda.setEnabled(false);
            //actualizo la lista de inscripcion, lo que genera una categoria p/c/inscripto
            new NegInscripcion().actualizaCategoriaInscriptos(ManagerTorneo.getInstance().getTorneo());
            diagEditCategoria diag = new diagEditCategoria(this, true);
            diag.setVisible(true);
            diag.dispose();
            ManagerTorneo.getInstance().fin_inscripcion();
            carrera_actual = ManagerTorneo.getInstance().getCompetencia_actual().getSiguienteCarrera();
            init();
        }catch(SQLException ex){
            System.err.println("sqlex: "+ex.getMessage());
        }catch(TodasCarrerasFinalizadasException ex){
            lblEstado.setText("todas las carreras han finalizado (wtf!)");
            System.err.println("carreras fin: "+ex.getMessage());
        }
    }
    private void inicia_comunicacion(){
        try{
            btnIniciarCarrera.setEnabled(false);
            ardmgr.inicializa_arduino();
//            btnCancelaCarrera.setEnabled(true);
//            btnInicioCarrera.setEnabled(false);
        }catch(IOException ex){
            System.out.println("ha ocurrido una exception "+ex.getMessage());
            
            ex.printStackTrace();
            javax.swing.JOptionPane.showMessageDialog(rootPane, "Verifique librerias de conexion", "Error Conexion", javax.swing.JOptionPane.WARNING_MESSAGE);
        }catch(RuntimeException ex){
            ex.printStackTrace();
            javax.swing.JOptionPane.showMessageDialog(rootPane, "Verifique que el puerto no este en uso", "Error Conexion", javax.swing.JOptionPane.WARNING_MESSAGE);
        }
    }
    
    /**
     * finaliza la conexion con el arduino y limpia la tabla 
     * para que puedan seleccionarse nuevos competidores
     */
    private void finaliza_comunicacion(){
        
        
        try{            
            btnIniciarCarrera.setEnabled(true);
            ardmgr.finaliza_arduino();
        }catch(NullPointerException ex){
            System.out.println("nunca inicie el arduino");
        }catch(Throwable t){
            CarrerasLogger.warn(frmCarrera.class, "throwable: "+t.getMessage());
        }
    }
    /**
     * intenta reinicar comunicacion con el arduino
     */
    private void reinicia_comunicacion(){
        finaliza_comunicacion();
        inicia_comunicacion();
    }
    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        pnlCorredores = new javax.swing.JPanel();
        jScrollPane1 = new javax.swing.JScrollPane();
        tblEstadoCorredores = new javax.swing.JTable();
        pnlOpcCorredores = new javax.swing.JPanel();
        btnAgregarCorredor = new javax.swing.JButton();
        btnFinInscripcion = new javax.swing.JButton();
        btnNuevaRonda = new javax.swing.JButton();
        pnlCarreraActual = new javax.swing.JPanel();
        pnlTiemposCompetidores = new javax.swing.JPanel();
        jScrollPane2 = new javax.swing.JScrollPane();
        tblTiempos = new javax.swing.JTable();
        jPanel7 = new javax.swing.JPanel();
        jPanel2 = new javax.swing.JPanel();
        jLabel2 = new javax.swing.JLabel();
        jLabel9 = new javax.swing.JLabel();
        jLabel4 = new javax.swing.JLabel();
        lblC1Numero = new javax.swing.JLabel();
        jLabel1 = new javax.swing.JLabel();
        lblC1Nombre = new javax.swing.JLabel();
        jLabel3 = new javax.swing.JLabel();
        lblC1Apellido = new javax.swing.JLabel();
        jLabel5 = new javax.swing.JLabel();
        lblC1Cat = new javax.swing.JLabel();
        jLabel7 = new javax.swing.JLabel();
        lblC1Auto = new javax.swing.JLabel();
        jPanel3 = new javax.swing.JPanel();
        jLabel10 = new javax.swing.JLabel();
        jLabel11 = new javax.swing.JLabel();
        jLabel6 = new javax.swing.JLabel();
        lblC2Numero = new javax.swing.JLabel();
        jLabel12 = new javax.swing.JLabel();
        lblC2Nombre = new javax.swing.JLabel();
        jLabel14 = new javax.swing.JLabel();
        lblC2Apellido = new javax.swing.JLabel();
        jLabel16 = new javax.swing.JLabel();
        lblC2Cat = new javax.swing.JLabel();
        jLabel18 = new javax.swing.JLabel();
        lblC2Auto = new javax.swing.JLabel();
        jPanel1 = new javax.swing.JPanel();
        btnIniciarCarrera = new javax.swing.JButton();
        jButton1 = new javax.swing.JButton();
        btnCerrar = new javax.swing.JButton();
        pnlEstadoGlobal = new javax.swing.JPanel();
        lblEstadoGlobal = new javax.swing.JLabel();
        lblEstado = new javax.swing.JLabel();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

        pnlCorredores.setBorder(javax.swing.BorderFactory.createTitledBorder("Corredores"));

        tblEstadoCorredores.setModel(new javax.swing.table.DefaultTableModel(
            new Object [][] {
                {"Carrera Finalizada", "", null},
                {"Corriendo", null, null},
                {"Corriendo", null, null},
                {"Esperando", null, null},
                {null, null, null}
            },
            new String [] {
                "Estado", "Numero", "Categoria"
            }
        ));
        jScrollPane1.setViewportView(tblEstadoCorredores);

        btnAgregarCorredor.setText("Agregar Corredor");
        btnAgregarCorredor.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btnAgregarCorredorActionPerformed(evt);
            }
        });
        pnlOpcCorredores.add(btnAgregarCorredor);

        btnFinInscripcion.setText("Fin Inscripcion");
        btnFinInscripcion.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btnFinInscripcionActionPerformed(evt);
            }
        });
        pnlOpcCorredores.add(btnFinInscripcion);

        btnNuevaRonda.setText("Nueva Ronda");
        btnNuevaRonda.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btnNuevaRondaActionPerformed(evt);
            }
        });
        pnlOpcCorredores.add(btnNuevaRonda);

        org.jdesktop.layout.GroupLayout pnlCorredoresLayout = new org.jdesktop.layout.GroupLayout(pnlCorredores);
        pnlCorredores.setLayout(pnlCorredoresLayout);
        pnlCorredoresLayout.setHorizontalGroup(
            pnlCorredoresLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(org.jdesktop.layout.GroupLayout.TRAILING, pnlOpcCorredores, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
            .add(jScrollPane1, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 435, Short.MAX_VALUE)
        );
        pnlCorredoresLayout.setVerticalGroup(
            pnlCorredoresLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(pnlCorredoresLayout.createSequentialGroup()
                .add(pnlOpcCorredores, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                .add(jScrollPane1, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 474, Short.MAX_VALUE))
        );

        pnlCarreraActual.setBorder(javax.swing.BorderFactory.createTitledBorder("Carrera Actual"));

        pnlTiemposCompetidores.setBorder(javax.swing.BorderFactory.createTitledBorder("Tiempos Corredores"));
        pnlTiemposCompetidores.setLayout(new java.awt.BorderLayout());

        tblTiempos.setModel(new javax.swing.table.DefaultTableModel(
            new Object [][] {
                {null, null, null, null},
                {null, null, null, null},
                {null, null, null, null},
                {null, null, null, null}
            },
            new String [] {
                "Title 1", "Title 2", "Title 3", "Title 4"
            }
        ));
        jScrollPane2.setViewportView(tblTiempos);

        pnlTiemposCompetidores.add(jScrollPane2, java.awt.BorderLayout.CENTER);

        jPanel7.setLayout(new java.awt.GridLayout(1, 0));

        jPanel2.setBorder(javax.swing.BorderFactory.createBevelBorder(javax.swing.border.BevelBorder.LOWERED));
        jPanel2.setLayout(new java.awt.GridLayout(0, 2));

        jLabel2.setText("Carril");
        jPanel2.add(jLabel2);

        jLabel9.setText("1");
        jPanel2.add(jLabel9);

        jLabel4.setText("Numero");
        jPanel2.add(jLabel4);
        jPanel2.add(lblC1Numero);

        jLabel1.setText("Nombre");
        jPanel2.add(jLabel1);
        jPanel2.add(lblC1Nombre);

        jLabel3.setText("Apellido");
        jPanel2.add(jLabel3);
        jPanel2.add(lblC1Apellido);

        jLabel5.setText("Categoria");
        jPanel2.add(jLabel5);
        jPanel2.add(lblC1Cat);

        jLabel7.setText("Auto");
        jPanel2.add(jLabel7);
        jPanel2.add(lblC1Auto);

        jPanel7.add(jPanel2);

        jPanel3.setBorder(javax.swing.BorderFactory.createBevelBorder(javax.swing.border.BevelBorder.LOWERED));
        jPanel3.setLayout(new java.awt.GridLayout(0, 2));

        jLabel10.setText("Carril");
        jPanel3.add(jLabel10);

        jLabel11.setText("2");
        jPanel3.add(jLabel11);

        jLabel6.setText("Numero");
        jPanel3.add(jLabel6);
        jPanel3.add(lblC2Numero);

        jLabel12.setText("Nombre");
        jPanel3.add(jLabel12);
        jPanel3.add(lblC2Nombre);

        jLabel14.setText("Apellido");
        jPanel3.add(jLabel14);
        jPanel3.add(lblC2Apellido);

        jLabel16.setText("Categoria");
        jPanel3.add(jLabel16);
        jPanel3.add(lblC2Cat);

        jLabel18.setText("Auto");
        jPanel3.add(jLabel18);
        jPanel3.add(lblC2Auto);

        jPanel7.add(jPanel3);

        btnIniciarCarrera.setText("Iniciar Carrera");
        btnIniciarCarrera.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btnIniciarCarreraActionPerformed(evt);
            }
        });
        jPanel1.add(btnIniciarCarrera);

        jButton1.setText("FuerzaFin");
        jButton1.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButton1ActionPerformed(evt);
            }
        });
        jPanel1.add(jButton1);

        btnCerrar.setText("Finalizar");
        btnCerrar.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btnCerrarActionPerformed(evt);
            }
        });
        jPanel1.add(btnCerrar);

        org.jdesktop.layout.GroupLayout pnlCarreraActualLayout = new org.jdesktop.layout.GroupLayout(pnlCarreraActual);
        pnlCarreraActual.setLayout(pnlCarreraActualLayout);
        pnlCarreraActualLayout.setHorizontalGroup(
            pnlCarreraActualLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(org.jdesktop.layout.GroupLayout.TRAILING, pnlTiemposCompetidores, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 737, Short.MAX_VALUE)
            .add(pnlCarreraActualLayout.createSequentialGroup()
                .add(jPanel1, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 729, Short.MAX_VALUE)
                .add(8, 8, 8))
            .add(org.jdesktop.layout.GroupLayout.TRAILING, jPanel7, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 737, Short.MAX_VALUE)
        );
        pnlCarreraActualLayout.setVerticalGroup(
            pnlCarreraActualLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(pnlCarreraActualLayout.createSequentialGroup()
                .add(jPanel7, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 263, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                .add(pnlTiemposCompetidores, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 185, Short.MAX_VALUE)
                .add(14, 14, 14)
                .add(jPanel1, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                .addContainerGap())
        );

        lblEstadoGlobal.setText("Estado Actual: Prueba Libre Nro: N / Competicion Ronda: N");
        pnlEstadoGlobal.add(lblEstadoGlobal);

        lblEstado.setText("Estado Comunicacion");
        lblEstado.setBorder(javax.swing.BorderFactory.createBevelBorder(javax.swing.border.BevelBorder.LOWERED));

        org.jdesktop.layout.GroupLayout layout = new org.jdesktop.layout.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(layout.createSequentialGroup()
                .addContainerGap()
                .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                    .add(pnlEstadoGlobal, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 1230, Short.MAX_VALUE)
                    .add(layout.createSequentialGroup()
                        .add(pnlCorredores, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(org.jdesktop.layout.LayoutStyle.UNRELATED)
                        .add(pnlCarreraActual, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                        .addContainerGap(org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))))
            .add(org.jdesktop.layout.GroupLayout.TRAILING, lblEstado, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 1250, Short.MAX_VALUE)
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(layout.createSequentialGroup()
                .addContainerGap()
                .add(pnlEstadoGlobal, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                .add(0, 0, 0)
                .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING, false)
                    .add(pnlCorredores, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .add(pnlCarreraActual, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                .add(18, 18, 18)
                .add(lblEstado, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 36, Short.MAX_VALUE))
        );

        pack();
    }// </editor-fold>//GEN-END:initComponents

    private void btnCerrarActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnCerrarActionPerformed
        finalizar_competicion_actual();
    }//GEN-LAST:event_btnCerrarActionPerformed

    private void btnAgregarCorredorActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnAgregarCorredorActionPerformed
        agregar_corredor();
    }//GEN-LAST:event_btnAgregarCorredorActionPerformed

    private void btnFinInscripcionActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnFinInscripcionActionPerformed
        fin_inscripcion();
    }//GEN-LAST:event_btnFinInscripcionActionPerformed

    private void btnIniciarCarreraActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnIniciarCarreraActionPerformed
        inicia_comunicacion();
    }//GEN-LAST:event_btnIniciarCarreraActionPerformed

    private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton1ActionPerformed
        fuerza_fin();
    }//GEN-LAST:event_jButton1ActionPerformed

    private void btnNuevaRondaActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnNuevaRondaActionPerformed
        nueva_ronda();
    }//GEN-LAST:event_btnNuevaRondaActionPerformed

    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        Configuracion.init_conf(args);
        /* Set the Nimbus look and feel */
        //<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
        /* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
         * For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html 
         */
        try {
            for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
                if ("Nimbus".equals(info.getName())) {
                    javax.swing.UIManager.setLookAndFeel(info.getClassName());
                    break;
                }
            }
        } catch (ClassNotFoundException ex) {
            java.util.logging.Logger.getLogger(frmCarrera.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (InstantiationException ex) {
            java.util.logging.Logger.getLogger(frmCarrera.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (IllegalAccessException ex) {
            java.util.logging.Logger.getLogger(frmCarrera.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (javax.swing.UnsupportedLookAndFeelException ex) {
            java.util.logging.Logger.getLogger(frmCarrera.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        }
        //</editor-fold>

        /* Create and display the form */
        java.awt.EventQueue.invokeLater(new Runnable() {

            public void run() {
                new frmCarrera().setVisible(true);
            }
        });
    }
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton btnAgregarCorredor;
    private javax.swing.JButton btnCerrar;
    private javax.swing.JButton btnFinInscripcion;
    private javax.swing.JButton btnIniciarCarrera;
    private javax.swing.JButton btnNuevaRonda;
    private javax.swing.JButton jButton1;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLabel jLabel10;
    private javax.swing.JLabel jLabel11;
    private javax.swing.JLabel jLabel12;
    private javax.swing.JLabel jLabel14;
    private javax.swing.JLabel jLabel16;
    private javax.swing.JLabel jLabel18;
    private javax.swing.JLabel jLabel2;
    private javax.swing.JLabel jLabel3;
    private javax.swing.JLabel jLabel4;
    private javax.swing.JLabel jLabel5;
    private javax.swing.JLabel jLabel6;
    private javax.swing.JLabel jLabel7;
    private javax.swing.JLabel jLabel9;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JPanel jPanel2;
    private javax.swing.JPanel jPanel3;
    private javax.swing.JPanel jPanel7;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JScrollPane jScrollPane2;
    private javax.swing.JLabel lblC1Apellido;
    private javax.swing.JLabel lblC1Auto;
    private javax.swing.JLabel lblC1Cat;
    private javax.swing.JLabel lblC1Nombre;
    private javax.swing.JLabel lblC1Numero;
    private javax.swing.JLabel lblC2Apellido;
    private javax.swing.JLabel lblC2Auto;
    private javax.swing.JLabel lblC2Cat;
    private javax.swing.JLabel lblC2Nombre;
    private javax.swing.JLabel lblC2Numero;
    private javax.swing.JLabel lblEstado;
    private javax.swing.JLabel lblEstadoGlobal;
    private javax.swing.JPanel pnlCarreraActual;
    private javax.swing.JPanel pnlCorredores;
    private javax.swing.JPanel pnlEstadoGlobal;
    private javax.swing.JPanel pnlOpcCorredores;
    private javax.swing.JPanel pnlTiemposCompetidores;
    private javax.swing.JTable tblEstadoCorredores;
    private javax.swing.JTable tblTiempos;
    // End of variables declaration//GEN-END:variables
//se podria implementar con un dtmodel que internamente haga un invokelater
//src: http://www.javakb.com/Uwe/Forum.aspx/java-gui/4968/Exception-in-Swing-code-using-a-JTable
//    private class TiemposTableModel extends DefaultTableModel{
//        public TiemposTableModel(Object object[], int row) {
//            super(object, row);
//        }
//
//        public TiemposTableModel() {
//            super();
//        }
//
//        @Override
//        public boolean isCellEditable(int row, int column) {
//            return false;
//        }
//    }
    
    
    
     private class CorredoresAutosEstadoRenderer implements TableCellRenderer {
        private DefaultTableCellRenderer default_cell_renderer;
        public CorredoresAutosEstadoRenderer(){
            default_cell_renderer = new DefaultTableCellRenderer();
        }
        @Override
        public Component getTableCellRendererComponent(JTable table, Object value,boolean isSelected, boolean hasFocus, int row, int column)  {
            if(isSelected){
                return default_cell_renderer.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
            }
//            Component renderer = default_cell_renderer.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
//            ((JLabel) renderer).setOpaque(true);
            JLabel renderer = new JLabel(value.toString());
            renderer.setOpaque(true);
            final Competencia competencia_actual = ManagerTorneo.getInstance().getCompetencia_actual();
            final CatCorredorAuto caV = competencia_actual.getCorredoresAutosActivos();
            CorredorAuto ca = caV.get(row);
            if(ca.getEstado_carrera()==CarrilCarrera.ESTADO_GANADOR){
                renderer.setBackground(Color.GREEN);
                return renderer;
            }else if(ca.getEstado_carrera()==CarrilCarrera.ESTADO_PERDEDOR){
                renderer.setBackground(Color.RED);
                return renderer;
            }else if(ca.getEstado_carrera()==CarrilCarrera.ESTADO_ESPERANDO_DATOS){
                renderer.setBackground(Color.BLUE);
                return renderer;
            }else if(ca.getEstado_carrera()==CarrilCarrera.ESTADO_ELIMINADO
                    || ca.getEstado_carrera()==CarrilCarrera.ESTADO_ADELANTADO
                    || ca.getEstado_carrera()==CarrilCarrera.ESTADO_ROTO){
                renderer.setBackground(Color.GRAY);
                return renderer;
            }
            return default_cell_renderer.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
        }
     }
     private class CorredoresAutosCategoriaRenderer implements TableCellRenderer {
        private DefaultTableCellRenderer default_cell_renderer;
        public CorredoresAutosCategoriaRenderer(){
            default_cell_renderer = new DefaultTableCellRenderer();
        }
        @Override
        public Component getTableCellRendererComponent(JTable table, Object value,boolean isSelected, boolean hasFocus, int row, int column)  {
            if(isSelected){
                return default_cell_renderer.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
            }
            JLabel renderer = new JLabel(value.toString());
            renderer.setOpaque(true);
            final Competencia competencia_actual = ManagerTorneo.getInstance().getCompetencia_actual();
            final CatCorredorAuto caV = competencia_actual.getCorredoresAutosActivos();
            CorredorAuto ca = caV.get(row);
            if(ca.getEstado_competencia()==CorredorAuto.ESTADO_COMPETENCIA_LIBRE){
                
            }else if(ca.getEstado_competencia()==CorredorAuto.ESTADO_COMPETENCIA_GANADOR){
                renderer.setBackground(new Color(23,246,200));
                return renderer;
            }else if(ca.getEstado_competencia()==CorredorAuto.ESTADO_COMPETENCIA_PERDEDOR){
                renderer.setBackground(new Color(243,189,99));
                return renderer;
            }
            
            return default_cell_renderer.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
        }
     }
    

}
